package com.sky.aop;

import com.sky.annotation.AutoFill;
import com.sky.context.BaseContext;
import com.sky.enumeration.OperationType;
import lombok.extern.slf4j.Slf4j;

import org.apache.commons.lang3.ObjectUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author chengjy
 * @date 2023/4/17
 */
@Aspect
@Component
@Slf4j
public class AutoFillField {
    //切入点表达式 && @annotation(com.sky.annotation.AutoFill)
    @Pointcut("execution(* com.sky.mapper.*.*(..) ) && @annotation(com.sky.annotation.AutoFill)")
    public void qieMian(){};

    //【前置通知】
    @Before("qieMian()")
    public void before(JoinPoint joinPoint) throws NoSuchFieldException, IllegalAccessException {
        log.info("AOP字段填充执行…………");
        //获得参数列表
        Object[] args = joinPoint.getArgs();
        if (ObjectUtils.isEmpty(args)) {
            return;
        }
        //拿到参数对象
        Object arg = args[0];
        //获取注解信息，为update或insert
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        AutoFill annotation = methodSignature.getMethod().getAnnotation(AutoFill.class);
        OperationType value = annotation.value();
        Class<?> clazz = arg.getClass();
        //将字段按字段名和字段对象封装成一个map，并生成一个方法管理
//        Map<String, Field> map = Arrays.asList(clazz.getDeclaredFields()).stream().collect(Collectors.toMap(f -> f.getName(), Function.identity()));
        Map<String, Field> fieldMap = Arrays.stream(clazz.getDeclaredFields()).collect(Collectors.toMap(field -> field.getName(), field -> field));

        if(OperationType.INSERT == value){
            fanSheAutoField(arg, fieldMap, "createTime");
            //通过反射得到字段信息，使用暴力反射给属性赋值
            fanSheAutoField(arg, fieldMap, "updateTime");

            //创建用户和修改用户
            fanSheAutoField(arg, fieldMap, "createUser");
            fanSheAutoField(arg, fieldMap, "updateUser");
        }else{
            //修改
            //通过反射得到字段信息，使用暴力反射给属性赋值
            fanSheAutoField(arg, fieldMap, "updateTime");
            fanSheAutoField(arg, fieldMap, "updateUser");
        }

    }

    private void fanSheAutoField(Object arg, Map<String, Field> fieldMap, String fieldName) throws NoSuchFieldException, IllegalAccessException {
        //通过反射得到字段信息，使用暴力反射给属性赋值
        Field field = fieldMap.get(fieldName);
        if(field == null){
            log.info("字段填充失败，无{}字段",fieldName);
            return;
        }
        field.setAccessible(true);
        if(field.getType() == LocalDateTime.class ){
            field.set(arg, LocalDateTime.now());
        }else{
            field.set(arg, BaseContext.getCurrentId());
        }
        log.info("字段填充成功，{}字段",fieldName);

    }

}
